unit UserSettings;

interface

uses
  Classes, Settings, Default, Colors, Success, Skills, Installation;

type
  TUserSettings = class
    public
      Settings: TSettings;
      Default: TDefault;
      Colors: TColors;
      Success: TSuccess;
      Skills: TSkills;
      Installations: TInstallation;

      constructor Create;
      destructor Destroy; reintroduce;
    private
      function LoadSettings_v041(stream: TMemoryStream): Boolean;
      function LoadSettings_v043(stream: TMemoryStream): Boolean;
      function LoadSettings_v044(stream: TMemoryStream): Boolean;
  end;

implementation

uses
  GlobalRecordsAndEnums, SysUtils, Dialogs, Forms;

constructor TUserSettings.Create;
var
  stream: TMemoryStream;
  version: Double;
begin
  Settings := TSettings.Create;
  Default := TDefault.Create;
  Colors := TColors.Create;
  Success := TSuccess.Create;
  Skills := TSkills.Create;
  Installations := TInstallation.Create;

  if (not FileExists('user\Settings.dat')) then begin
    MessageDlg('Unable to locate the file ' + ExtractFileDir(Application.ExeName) + '\user\Settings.dat.', mtError, [mbOk], 0);
  end
  else begin
    stream := TMemoryStream.Create;
    stream.Position := 0;
    stream.LoadFromFile('user\Settings.dat');
    try
      stream.Read(version, sizeof(Double));
    except
      MessageDlg('Error reading Settings.dat: invalid version information.', mtError, [mbOk], 0);
      stream.Free;
      exit;
    end;
    if (Round(version * 100) = 41) then // just 0.41 seems to result in a precision error
      self.LoadSettings_v041(stream)
    else if (Round(version * 100) = 43) then
      self.LoadSettings_v043(stream)
    else if (Round(version * 100) = 44) then
      self.LoadSettings_v044(stream)
    else begin
      MessageDlg('Error reading Settings.dat: no suitable load function found.', mtError, [mbOk], 0);
    end;
    stream.Free;
  end;
end;

destructor TUserSettings.Destroy;
var
  stream: TMemoryStream;
  sset: SSettings_v044;
  sdef: SDefault;
  scol: SColor;
  ssuc: SSuccess;
  sskill: SSkills;
  sinst: SInstallation;
  version: Double;
begin
  version := 0.44;
  stream := TMemoryStream.Create;
  stream.Write(version, SizeOf(Double));
  sset := Settings.Save;
  stream.Write(sset, SizeOf(SSettings_v044));
  sdef := Default.Save;
  stream.Write(sdef, SizeOf(SDefault));
  scol := Colors.Save;
  stream.Write(scol, SizeOf(SColor));
  ssuc := Success.Save;
  stream.Write(ssuc, SizeOf(SSuccess));
  sskill := Skills.Save;
  stream.Write(sskill, SizeOf(SSkills));
  sinst := Installations.Save;
  stream.Write(sinst, SizeOf(SInstallation));
  try
    stream.SaveToFile('user\Settings.dat');
  except
    on e: Exception do MessageDlg(e.Message, mtError, [mbOk], 0);
  end;
  stream.Free;

  Settings.Destroy;
  Default.Destroy;
  Colors.Destroy;
  Success.Destroy;
  Skills.Destroy;
  Installations.Destroy;

  Inherited Destroy;
end;

function TUserSettings.LoadSettings_v041(stream: TMemoryStream): Boolean;
var
  sset: SSettings;
  sdef: SDefault;
  scol: SColor;
  ssuc: SSuccess;
  sskill: SSkills;
  sinst: SInstallation;
begin
  result := true;
  try
    stream.Read(sset, sizeof(SSettings));
    Settings.Load(sset);
  except
    MessageDlg('Error reading Settings.dat: invalid settings', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sdef, sizeof(SDefault));
    Default.Load(sdef);
  except
    MessageDlg('Error reading Settings.dat: invalid defaults', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(scol, sizeof(SColor));
    Colors.Load(scol);
  except
    MessageDlg('Error reading Settings.dat: invalid colors', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(ssuc, sizeof(SSuccess));
    Success.Load(ssuc);
  except
    MessageDlg('Error reading Settings.dat: invalid formula', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sskill, sizeof(SSkills));
    Skills.Load(sskill);
  except
    MessageDlg('Error reading Settings.dat: invalid skills', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sinst, sizeof(SInstallation));
    Installations.Load(sinst);
  except
    MessageDlg('Error reading Settings.dat: invalid installations', mtError, [mbOk], 0);
    result := false;
    exit;
  end;
end;

function TUserSettings.LoadSettings_v043(stream: TMemoryStream): Boolean;
var
  sset: SSettings_v043;
  sdef: SDefault;
  scol: SColor;
  ssuc: SSuccess;
  sskill: SSkills;
  sinst: SInstallation;
begin
  result := true;
  try
    stream.Read(sset, sizeof(SSettings_v043));
    Settings.Load(sset);
  except
    MessageDlg('Error reading Settings.dat: invalid settings', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sdef, sizeof(SDefault));
    Default.Load(sdef);
  except
    MessageDlg('Error reading Settings.dat: invalid defaults', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(scol, sizeof(SColor));
    Colors.Load(scol);
  except
    MessageDlg('Error reading Settings.dat: invalid colors', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(ssuc, sizeof(SSuccess));
    Success.Load(ssuc);
  except
    MessageDlg('Error reading Settings.dat: invalid formula', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sskill, sizeof(SSkills));
    Skills.Load(sskill);
  except
    MessageDlg('Error reading Settings.dat: invalid skills', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sinst, sizeof(SInstallation));
    Installations.Load(sinst);
  except
    MessageDlg('Error reading Settings.dat: invalid installations', mtError, [mbOk], 0);
    result := false;
    exit;
  end;
end;

function TUserSettings.LoadSettings_v044(stream: TMemoryStream): Boolean;
var
  sset: SSettings_v044;
  sdef: SDefault;
  scol: SColor;
  ssuc: SSuccess;
  sskill: SSkills;
  sinst: SInstallation;
begin
  result := true;
  try
    stream.Read(sset, sizeof(SSettings_v044));
    Settings.Load(sset);
  except
    MessageDlg('Error reading Settings.dat: invalid settings', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sdef, sizeof(SDefault));
    Default.Load(sdef);
  except
    MessageDlg('Error reading Settings.dat: invalid defaults', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(scol, sizeof(SColor));
    Colors.Load(scol);
  except
    MessageDlg('Error reading Settings.dat: invalid colors', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(ssuc, sizeof(SSuccess));
    Success.Load(ssuc);
  except
    MessageDlg('Error reading Settings.dat: invalid formula', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sskill, sizeof(SSkills));
    Skills.Load(sskill);
  except
    MessageDlg('Error reading Settings.dat: invalid skills', mtError, [mbOk], 0);
    result := false;
    exit;
  end;

  try
    stream.Read(sinst, sizeof(SInstallation));
    Installations.Load(sinst);
  except
    MessageDlg('Error reading Settings.dat: invalid installations', mtError, [mbOk], 0);
    result := false;
    exit;
  end;
end;

end.
